package com.iw.adoms.service;

import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import com.iw.adoms.utils.QrCodeUtil;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.Model;

import com.iw.adoms.dao.DepartmentDao;
import com.iw.adoms.dao.GoodsDao;
import com.iw.adoms.dao.OrderDao;
import com.iw.adoms.dao.OrderLineDao;
import com.iw.adoms.dao.QrBoxCodeDao;
import com.iw.adoms.dao.QrGoodsCodeDao;
import com.iw.adoms.dao.StorageBatchDao;
import com.iw.adoms.entity.Department;
import com.iw.adoms.entity.Goods;
import com.iw.adoms.entity.Order;
import com.iw.adoms.entity.OrderLine;
import com.iw.adoms.entity.QrBoxCode;
import com.iw.adoms.entity.QrGoodsCode;
import com.iw.adoms.entity.StorageBatch;
import com.iw.adoms.entity.neum.DepartType;
import com.iw.adoms.entity.neum.FullStatus;
import com.iw.adoms.entity.neum.Status;
import com.iw.core.orm.Filtration;
import com.iw.core.orm.Filtration.MatchType;
import com.iw.core.orm.hibernate.BaseDao;
import com.iw.core.orm.hibernate.BaseService;
import com.iw.core.security.entity.Users;

@Service
@Transactional
public class GoodsService extends BaseService<Goods> {
	@Override
	@Resource(name = "goodsDao")
	public void setBaseDao(BaseDao<Goods> baseDao) {
		this.baseDao = baseDao;
	}

	@Autowired
	private DepartmentDao departmentDao;

	@Autowired
	private GoodsDao goodsDao;
	@Autowired
	private OrderDao orderDao;
	@Autowired
	private QrGoodsCodeDao qrGoodsCodeDao;
	@Autowired
	private QrBoxCodeDao qrBoxCodeDao;
	@Autowired
	private OrderLineDao orderLineDao;
	@Autowired
	private StorageBatchDao storageBatchDao;

	public List<Goods> getStockListByMidAndDid(Integer mid, Integer did) {

		return goodsDao.getStockListByMidAndDid(mid, did);
	}

	public List<Goods> getStockListByMid(Integer mid) {
		return goodsDao.getStockListByMid(mid);
	}

	public void outStock(Order order, Integer[] goodsId, HttpServletRequest request) throws Exception {
		Order o = orderDao.find(order.getId());
		o.setMemo3(order.getMemo3());
		o.setOutUser(order.getOutUser());
		o.setStatus(Status.ORDER_HAS_SHIPED);
		o.setOutTime(new Date());
		for (Integer id : goodsId) {
			Goods goods = this.find(id);
			goods.setOrder(o);
			goods.setState(Status.HAS_OUT.getValue());
			this.update(goods);
		}
		Users user = (Users) request.getSession().getAttribute("USER");
		FullStatus fStatus = null;
		Department department = departmentDao.find(user.getDepartment().getId());

		if (DepartType.ZD.v().equals(department.getType().getName())) {
			fStatus = FullStatus.ZDYFH;
		} else if (DepartType.SD.v().equals(department.getType().getName())) {
			fStatus = FullStatus.SDYFH;
		} else if (DepartType.MD.v().equals(department.getType().getName())) {
			fStatus = FullStatus.MDYFH;
		}
		o.setfStatus(fStatus);
		o.addLogs(user, "出库发货"); // 记录日志
		orderDao.update(o); // 注这个位置，让上面的状态更新完了，这里才更新这个order的状态，这里的先后顺序会影响库存明细的统计
	}

	/**
	 * pda 出库
	 * 
	 * @param user
	 * @param model
	 * @param request
	 * @param qrCode
	 * @param orderLineId
	 * @param orderId
	 * @return
	 */
	public String pdaOut(Users user, Model model, HttpServletRequest request, String qrCode, Integer[] orderLineId, Integer orderId, Integer departmentId) throws Exception {
		Order order = orderDao.find(orderId); // 取出当前操作的订单
		String msg = "";
		boolean qrFlag = false; // 二维码是否录入成功
		boolean isOrderFull = true; // 订单录入是否完成
		boolean isNumberMore = false;
		try {
			List<Goods> willOutList = new ArrayList<Goods>(); // 要出库的goods结果集
			Integer did = user.getDepartment().getId(); // 取得当前部门的ID
			qrCode = qrCode.trim().replace(" ", "");
//            http://qr.alvinbaby.com?100001066618

            //2013.10.10
            String wCode = QrCodeUtil.getCode(qrCode);

			/*** 按录入的二维码查询到相应要出库的Goods ***/
			// 1. 先判断是否为箱码，先查询箱码
			String hql = "from Goods where qrCode.box.wCode = ? and department.id = ? and state = ?";
			List<Goods> goodsList = this.findList(hql, wCode, did, Status.WILL_SALE.getValue());
			if (!goodsList.isEmpty()) {
				if (goodsList.size() == goodsList.get(0).getQrCode().getBox().getGoodsNum()) {
					willOutList.addAll(goodsList);
				} else {
					msg = qrCode + "<span style='color:red;'>该箱已被开箱，箱码失效，请单个扫描！</span>";
				}
			} else {
				// 2. 只是单纯的货物二维码
				hql = "from Goods where qrCode.wCode = ? and department.id = ? and state = ?";
				Goods goods = this.find(hql, wCode, did, Status.WILL_SALE.getValue()); // 只是货物二维码，不是箱码的时候
				if (goods != null) {
					willOutList.add(goods);
				}
			}

			// 查询出来要出库的goods，根据这个goods来更新相应的orderLine
			if (!willOutList.isEmpty()) {

				// 有出库的商品了，那就先查询当前这个订单中的所有orderLine
				List<OrderLine> lineList = new ArrayList<OrderLine>();
				for (Integer lineId : orderLineId) {
					OrderLine orderLine = orderLineDao.find(lineId);
					lineList.add(orderLine);
				}

				for (OrderLine orderLine : lineList) {
					boolean more = true;
					for (Goods goods : willOutList) {
						// 二维码和订购的商品相同时才作处理
						if (goods.getMarchandise().getId().equals(orderLine.getMarchandise().getId())) {
							if (more && willOutList.size() > 1 && (orderLine.getItems() - orderLine.getHasIn() < willOutList.size())) {
								msg = qrCode + "录入数量超过剩余录入数量，请单个商品录入";
								isNumberMore = true;
								break;
							}
							more = false;
							// 只有未录入满的orderline才录入
							if (orderLine.getHasIn() < orderLine.getItems()) {
								// 更新goods的状态，并设置其出库所属哪个一订单order
								goods.setOrder(order);
								goods.setState(Status.HAS_OUT.getValue());
								this.update(goods);
								// 更新orderline中的计数
								orderLine.setHasIn(orderLine.getHasIn() + 1);
								orderLine.setHasleft(orderLine.getItems() - orderLine.getHasIn());
								// 更新标志
								qrFlag = true;
							} else {
								break;
							}

						}
					}
				}

				// 出库goods处理完成后再处理orderLine,将其状态更新到数据库
				for (OrderLine orderLine : lineList) {
					if (orderLine.getHasIn() < orderLine.getItems()) {
						isOrderFull = false;// 订单是否完成标志
					}
					orderLineDao.update(orderLine);
				}
			}

			if (StringUtils.isBlank(msg)) {
				// 设置二维码状态
				if (qrFlag) {
					msg = qrCode + "录入成功";
					// 设置订单状态
					if (isOrderFull) {
						order.setMemo3("PDA订单出库");
						order.setOutUser(user.getName());
						order.setStatus(Status.ORDER_HAS_SHIPED);
						FullStatus fStatus = FullStatus.ZDYFH;
						Department department = departmentDao.find(user.getDepartment().getId());
						if (DepartType.SD.v().equals(department.getType().getName())) {
							fStatus = FullStatus.SDYFH;
						} else if (DepartType.MD.v().equals(department.getType().getName())) {
							fStatus = FullStatus.MDYFH;
						}
						order.setfStatus(fStatus);
						order.setOutTime(new Date());
						msg += "<br/>订单：" + order.getCode() + "出库完成.";
						
						
						order.addLogs(user, "出库发货"); // 记录日志
						
						orderDao.update(order);
					}
				} else {
					if (isNumberMore) {
						msg = qrCode + "录入数量超过剩余录入数量，请单个商品录入";
					} else {
						if (qrCode.length() == 36) {
							msg = qrCode + " <span style='color:red;'>已被使用</span>";
						} else {
							msg = qrCode + " <span style='color:red;'>无效</span>";
						}
					}
				}
			}

		} catch (Exception e) {
			e.printStackTrace();
			msg = qrCode + " <span style='color:red;'>无效</span>";
		}
		model.addAttribute("order", order); // 处理的哪个订单还是要返回到页面上去的
		model.addAttribute("msg", msg);
		if (msg.endsWith("出库完成.")) {
			List<OrderLine> orderLines = orderLineDao.findList("order.id", order.getId());
			model.addAttribute("orderLines", orderLines);
		}
		commonOut(model, departmentId);
		return msg;
	}

	/**
	 * 根据 batch 和 qrCode 将货物入库，并反回相应的消息
	 * 
	 * @param qrCode
	 * @param batch
	 * @return msg
	 */
	public String inStore(String qrCode, Integer batchId, Model model, Integer departmentId) {
		qrCode = qrCode.trim().replace(" ", "");
        //2013.10.10
        String wCode = QrCodeUtil.getCode(qrCode);
		StorageBatch batch = storageBatchDao.find(batchId);
		int numOfStore = 0; // 入库数量
		commonPda(model, departmentId);
		model.addAttribute("inBatch", batch);
		// 先查询箱码
		QrBoxCode box = qrBoxCodeDao.find("wCode", wCode);
		if (box != null && box.getState().equals(Status.WILL_IN.getValue())) {

			// 判断规格是否正确
			if (!box.getGoodsNum().equals(batch.getMarchandise().getNumOfBox())) {
				return qrCode + " 箱码规格不正确";
			}

			// 取得本箱中未入库的二维码
			Filtration boxFilter = new Filtration(MatchType.EQ, box.getId(), "box.id");
			Filtration stateFilter = new Filtration(MatchType.EQ, Status.WILL_IN.getValue(), "state");
			List<QrGoodsCode> gList = qrGoodsCodeDao.findList(boxFilter, stateFilter);
			if (gList != null && gList.size() > 0) {
				if (gList.size() != box.getGoodsNum()) {
					return qrCode + "该箱已被开箱，箱码失效，请单个扫描！";
				}
				if (gList.size() > (batch.getNumOfMarchandise() - batch.getNumOfMarchandiseHasDone())) {
					return qrCode + "箱码中货物数量超过限制，请单个商品录入！";
				}
				// 新增货物 入库的时候没有设置部门ID
				for (QrGoodsCode goodQr : gList) {
					Goods goods = new Goods();
					goods.setDepartment(batch.getDepartment());
					goods.setMarchandise(batch.getMarchandise());
					goods.setProduceDate(batch.getProduceDate());
					goods.setStorageBatch(batch);
					goods.setQrCode(goodQr);
					goods.setId(null);
					goods.setState(Status.WILL_SALE.getValue());
					this.save(goods); //
					// 更新货物二维码表中的状态
					goodQr.setState(Status.HAS_IN.getValue());
					goodQr.setStorageBatch(batch);
					qrGoodsCodeDao.update(goodQr);
					numOfStore++;
				}
			}
			// 更新箱码的状态
			box.setState(Status.HAS_IN.getValue());
			box.setStorageBatch(batch);
			qrBoxCodeDao.update(box);
		} else {// 不是箱码
			QrGoodsCode goodQr = qrGoodsCodeDao.find("wCode", wCode);
			if (goodQr != null && goodQr.getState().equals(Status.WILL_IN.getValue())) {
				if (!goodQr.getBox().getGoodsNum().equals(batch.getMarchandise().getNumOfBox())) {
					return qrCode + " 规格不正确";
				}
				Goods goods = new Goods();
				goods.setDepartment(batch.getDepartment());
				goods.setMarchandise(batch.getMarchandise());
				goods.setProduceDate(batch.getProduceDate());
				goods.setStorageBatch(batch);
				goods.setQrCode(goodQr);
				goods.setId(null);
				goods.setState(Status.WILL_SALE.getValue());
				this.save(goods); //
				// 更新货物二维码表中的状态
				goodQr.setState(Status.HAS_IN.getValue());
				goodQr.setStorageBatch(batch);
				qrGoodsCodeDao.update(goodQr);
				numOfStore++;
			}
		}
		if (numOfStore > 0) {
			// 更新完成的数量
			DecimalFormat df = new DecimalFormat("######0.00");
			batch.setNumOfMarchandiseHasDone(batch.getNumOfMarchandiseHasDone() + numOfStore);
			batch.setNumOfBoxHasDone(Double.valueOf(df.format(batch.getNumOfMarchandiseHasDone() / batch.getMarchandise().getNumOfBox().doubleValue())));
			// 更新批次的状态
			if (batch.getNumOfMarchandise().equals(batch.getNumOfMarchandiseHasDone())) {
				batch.setState(FullStatus.ZDYWC.v());
				storageBatchDao.update(batch);
				return qrCode + " 录入成功 <br/>入库单:" + batch.getBatchCode() + " 录入完成";
			} else {
				batch.setState(FullStatus.ZDRKZ.v());
				storageBatchDao.update(batch);
				return qrCode + " 录入成功";
			}
		} else {
			if (qrCode.length() == 36) {
				return qrCode + " <span style='color:red;'>已被使用</span>";
			} else {
				return qrCode + " <span style='color:red;'>无效</span>";
			}
		}
	}

	/**
	 * 获取下拉入库单
	 * 
	 * @param model
	 * @param request
	 */
	public void commonPda(Model model, Integer departmentId) {
		String hql = "from StorageBatch where department.id = ? and state != ? and state != ?";
		List<StorageBatch> batchList = storageBatchDao.findList(hql, departmentId, Status.STORAGE_BATCH_DONE.getValue(), FullStatus.ZDYWC.v());
		model.addAttribute("batchList", batchList);
	}

	/**
	 * 清除当前入库批次的所有数据
	 * 
	 * @param batchId
	 * @return boolean
	 */
	public void clearStoreData(Integer batchId, Model model, Integer departmentId) {
		String msg = "";
		try {
			String hql = "delete from Goods where storageBatch.id = ?";
			goodsDao.batchExecute(hql, batchId);
			String hql2 = "update QrGoodsCode set state = ? where storageBatch.id = ?";
			qrGoodsCodeDao.batchExecute(hql2, Status.WILL_IN.getValue(), batchId);
			String hql4 = "update QrBoxCode set state = ? where storageBatch.id = ?";
			qrBoxCodeDao.batchExecute(hql4, Status.WILL_IN.getValue(), batchId);
			String hql3 = "update StorageBatch set state=?,numOfBoxHasDone = 0,numOfMarchandiseHasDone = 0 where id=?";
			storageBatchDao.batchExecute(hql3, Status.STORAGE_BATCH_WILL_IN.getValue(), batchId);
			msg = "数据清除成功";
		} catch (Exception e) {
			msg = "数据清除失败";
		}
		StorageBatch batch = storageBatchDao.find(batchId);
		// 入库
		model.addAttribute("inBatch", batch);
		model.addAttribute("msg", msg);
		// 设置下拉列表
		commonPda(model, departmentId);
	}

	/**
	 * 获取下拉入库单
	 * 
	 * @param model
	 * @param request
	 */
	public void commonOut(Model model, Integer departmentId) {
		List<Order> orderList = orderDao.findList("from Order where ((departmentTarget.id=? and type=? ) or (department.id=? and type=?)) and status=?", departmentId, true, departmentId, false,
				Status.ORDER_WILL_SHIP);
		model.addAttribute("orderList", orderList);
	}

	/**
	 * 清除当前出库批次的所有数据
	 * 
	 * @param batchId
	 * @return boolean
	 */
	public void clearOutData(Integer orderId, Model model, Integer departmentId) {
		String msg = "";
		try {
			String hql = "update Goods set state=? where order.id = ?";
			goodsDao.batchExecute(hql, Status.WILL_SALE.getValue(), orderId);
			String hql2 = "update OrderLine set hasIn = 0,hasleft = 0 where order.id = ?";
			orderLineDao.batchExecute(hql2, orderId);
			msg = "数据清除成功";
		} catch (Exception e) {
			msg = "数据清除失败";
		}
		Order order = orderDao.find(orderId); // 取出当前操作的订单
		// 入库
		model.addAttribute("order", order); // 处理的哪个订单还是要返回到页面上去的
		model.addAttribute("msg", msg);
		// 设置下拉列表
		commonOut(model, departmentId);
	}

}
